#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
C#脚本编辑器 - 基于PyQt5
"""

import sys
import os
import re
import json
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QColor
from PyQt5.Qsci import QsciScintilla, QsciLexerCPP, QsciAPIs, QsciLexerCustom
from PyQt5.QtWidgets import QInputDialog, QDialogButtonBox, QMenu

class SnippetDialog(QDialog):
    def __init__(self, parent=None, name="", content=""):
        super().__init__(parent)
        self.setWindowTitle("编辑代码片段")
        self.setModal(True)
        self.resize(500, 300)
        
        layout = QVBoxLayout()
        
        # 名称输入
        form_layout = QFormLayout()
        self.name_edit = QLineEdit(name)
        form_layout.addRow("片段名称:", self.name_edit)
        
        # 内容输入
        self.content_edit = QTextEdit()
        self.content_edit.setPlainText(content)
        self.content_edit.setFont(QFont("Consolas", 10))
        
        # 按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        
        layout.addLayout(form_layout)
        layout.addWidget(QLabel("片段内容:"))
        layout.addWidget(self.content_edit)
        layout.addWidget(button_box)
        
        self.setLayout(layout)
    
    def get_data(self):
        return self.name_edit.text(), self.content_edit.toPlainText()

class SyntaxChecker:
    @staticmethod
    def check_syntax(text):
        errors = []
        warnings = []
        
        if not text.strip():
            errors.append("文件为空")
            return errors, warnings
        
        # 检查region配对
        regions = re.findall(r'#region', text)
        endregions = re.findall(r'#endregion', text)
        if len(regions) != len(endregions):
            errors.append(f"#region和#endregion不匹配")
        
        # 检查大括号配对
        open_braces = text.count('{')
        close_braces = text.count('}')
        if open_braces != close_braces:
            errors.append(f"大括号不匹配")
        
        return errors, warnings

class TnDeleteDialog(QDialog):
    def __init__(self, parent, max_n):
        super().__init__(parent)
        self.setWindowTitle("选择要删除的Tn编号")
        self.resize(300, 400)
        layout = QVBoxLayout()
        self.list_widget = QListWidget()
        self.list_widget.setSelectionMode(QListWidget.MultiSelection)
        for i in range(1, max_n+1):
            self.list_widget.addItem(f"T{i}")
        layout.addWidget(self.list_widget)
        btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self.accept)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)
        self.setLayout(layout)
    def get_selected(self):
        return [int(item.text()[1:]) for item in self.list_widget.selectedItems()]

class MyScintilla(QsciScintilla):
    def contextMenuEvent(self, event):
        menu = QMenu(self)
        act_cut = menu.addAction("剪切")
        act_copy = menu.addAction("复制")
        act_paste = menu.addAction("粘贴")
        act_selectall = menu.addAction("全选")
        act_cut.triggered.connect(self.cut)
        act_copy.triggered.connect(self.copy)
        act_paste.triggered.connect(self.paste)
        act_selectall.triggered.connect(self.selectAll)
        menu.exec_(event.globalPos())

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            urls = event.mimeData().urls()
            if urls:
                file_path = urls[0].toLocalFile()
                if os.path.isfile(file_path):
                    # 让主窗口处理文件打开
                    mw = self.window()
                    if hasattr(mw, 'open_files_from_drop'):
                        mw.open_files_from_drop([u.toLocalFile() for u in urls])
        else:
            event.ignore()

class ScriptEditor(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("C#脚本编辑器")
        self.resize(1000, 700)
        self.setAcceptDrops(True)  # 支持拖拽
        self.opened_files = []  # [{filename, content, modified}]
        self.current_file_index = -1
        self.window_menu = None  # 初始化window_menu，防止未定义
        self.snippets = self.load_snippets()
        self.setup_ui()
        self.setup_editor()
        self.setup_menu()
    
    def load_snippets(self):
        if os.path.exists("snippets.json"):
            with open("snippets.json", "r", encoding="utf-8") as f:
                data = json.load(f)
            return {item["name"]: item["content"] for item in data}
        # 默认片段
        return {
            "显示": "#region//显示\n//实例化文本显示\n//初始化图形显示\n#endregion\n",
            "实例化工具": "#region//实例化工具\n// ...\n#endregion\n",
            "判断模板匹配工具": "//判断模板匹配工具\n",
            "运行检测工具": "#region//运行检测工具\n// ...\n#endregion\n",
            "判断检测项结果": "//判断检测项结果\n",
            "最终判断": "#region//最终判断\n// ...\n#endregion\n",
            "When the Last Run Record is Created": "#region When the Last Run Record is Created\n// ...\n#endregion\n",
            "基本类结构": """#region namespace imports\nusing System;\nusing System.Collections;\nusing System.Drawing;\nusing System.IO;\nusing System.Windows.Forms;\nusing Cognex.VisionPro;\nusing Cognex.VisionPro.ToolBlock;\nusing Cognex.VisionPro3D;\nusing Cognex.VisionPro.PMAlign;\nusing Cognex.VisionPro.CalibFix;\nusing Cognex.VisionPro.Blob;\nusing Cognex.VisionPro.ImageProcessing;\n#endregion\n\npublic class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase\n{\n    #region Private Member Variables\n    private Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;\n    #endregion\n\n    public override bool GroupRun(ref string message, ref CogToolResultConstants result)\n    {\n        // 在这里添加您的代码\n        return false;\n    }\n}""",
            "PMAlign工具": """CogPMAlignTool mPMAlign1 = mToolBlock.Tools[\"产品模板匹配\"] as CogPMAlignTool;\nCogFixtureTool mFixture = mToolBlock.Tools[\"定位\"] as CogFixtureTool;""",
            "图形显示": """CogGraphicLabel myLabel = new CogGraphicLabel();\nmyLabel.Text = \"\";\nmyLabel.X = 2800;\nmyLabel.Y = 0;\nmyLabel.Color = CogColorConstants.Green;\nmyLabel.Font = new Font(\"宋体\", 12);\nmyLabel.SelectedSpaceName = \"#\";\nmyLabel.Alignment = CogGraphicLabelAlignmentConstants.TopLeft;""",
            "输出设置": """mToolBlock.Outputs[\"RunMessage\"].Value = \"\";\nmToolBlock.Outputs[\"Result\"].Value = \"\";\nmToolBlock.Outputs[\"SendData\"].Value = \"D102,0\";""",
            "条件判断": """if(mPMAlign1.RunStatus.Result.ToString() != \"Accept\" || mPMAlign1.Results.Count != 1)\n{\n    mToolBlock.Outputs[\"RunMessage\"].Value = \"模板匹配失败\";\n    mToolBlock.Outputs[\"Result\"].Value = \"NG\";\n    mToolBlock.Outputs[\"SendData\"].Value = \"D102,2\";\n}""",
            "图形记录": """mToolBlock.AddGraphicToRunRecord(myLabel, lastRecord, lastRecord.SubRecords[1].RecordKey, \"\");\nif(T1)\n{\n    mToolBlock.AddGraphicToRunRecord(rect1s, lastRecord, lastRecord.SubRecords[1].RecordKey, \"script\");\n}"""
        }
    
    def setup_ui(self):
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        splitter = QSplitter(Qt.Horizontal)
        # 左侧面板
        left_panel = QWidget()
        left_layout = QVBoxLayout()
        self.snippet_list = QListWidget()
        self.snippet_list.itemDoubleClicked.connect(self.insert_snippet_from_list)
        self.refresh_snippet_list()
        # 片段管理按钮
        buttons_layout = QHBoxLayout()
        add_btn = QPushButton("添加片段")
        edit_btn = QPushButton("编辑片段")
        del_btn = QPushButton("删除片段")
        up_btn = QPushButton("上移")
        down_btn = QPushButton("下移")
        add_btn.clicked.connect(self.add_snippet)
        edit_btn.clicked.connect(self.edit_snippet)
        del_btn.clicked.connect(self.delete_snippet)
        up_btn.clicked.connect(self.move_snippet_up)
        down_btn.clicked.connect(self.move_snippet_down)
        buttons_layout.addWidget(add_btn)
        buttons_layout.addWidget(edit_btn)
        buttons_layout.addWidget(del_btn)
        buttons_layout.addWidget(up_btn)
        buttons_layout.addWidget(down_btn)
        left_layout.addWidget(QLabel("代码片段:"))
        left_layout.addWidget(self.snippet_list)
        left_layout.addLayout(buttons_layout)
        left_panel.setLayout(left_layout)
        splitter.addWidget(left_panel)
        # 右侧只保留一个编辑器
        self.editor = MyScintilla()
        # 设置C++高亮和编辑器外观
        font = QFont("Consolas", 11)
        self.editor.setFont(font)
        lexer = QsciLexerCPP()
        lexer.setFont(font)
        self.editor.setLexer(lexer)
        self.editor.setMarginType(0, QsciScintilla.NumberMargin)
        self.editor.setMarginWidth(0, "000")
        self.editor.setAutoIndent(True)
        self.editor.setIndentationGuides(True)
        self.editor.setTabWidth(4)
        self.editor.setUtf8(True)
        self.editor.setPaper(QColor(43, 43, 43))
        self.editor.setColor(QColor(169, 183, 198))
        self.editor.textChanged.connect(self.on_text_changed)
        splitter.addWidget(self.editor)
        splitter.setSizes([250, 750])
        layout = QVBoxLayout()
        layout.addWidget(splitter)
        central_widget.setLayout(layout)
        self.statusBar().showMessage("就绪")

    def setup_editor(self):
        self.new_file()
    
    # 删除所有tab_widget相关方法和属性，保留单一编辑器逻辑
    # 删除add_new_tab、close_tab、current_editor、current_filename、set_current_filename、set_current_modified等方法
    # update_window_menu方法中只遍历self.opened_files，不再引用tab_widget
    def current_filename(self):
        idx = self.current_file_index
        return self.opened_files[idx]["filename"] if 0 <= idx < len(self.opened_files) else None
    
    def set_current_filename(self, filename):
        idx = self.current_file_index
        if 0 <= idx < len(self.opened_files):
            self.opened_files[idx]["filename"] = filename
            self.update_title_status()
    
    def set_current_modified(self, modified):
        idx = self.current_file_index
        if 0 <= idx < len(self.opened_files):
            self.opened_files[idx]["modified"] = modified
            self.update_title_status()
    
    def update_title_status(self):
        idx = self.current_file_index
        filename = self.opened_files[idx]["filename"] if 0 <= idx < len(self.opened_files) else None
        modified = self.opened_files[idx]["modified"] if 0 <= idx < len(self.opened_files) else False
        if filename:
            self.setWindowTitle(f"C#脚本编辑器 - {os.path.basename(filename)}{' *' if modified else ''}")
        else:
            self.setWindowTitle(f"C#脚本编辑器{' *' if modified else ''}")
    
    def setup_menu(self):
        menubar = self.menuBar()
        # 文件菜单
        file_menu = menubar.addMenu("文件")
        new_action = QAction("新建", self)
        new_action.setShortcut("Ctrl+N")
        new_action.triggered.connect(self.new_file)
        file_menu.addAction(new_action)
        open_action = QAction("打开", self)
        open_action.setShortcut("Ctrl+O")
        open_action.triggered.connect(self.open_file)
        file_menu.addAction(open_action)
        save_action = QAction("保存", self)
        save_action.setShortcut("Ctrl+S")
        save_action.triggered.connect(self.save_file)
        file_menu.addAction(save_action)
        saveas_action = QAction("另存为", self)
        saveas_action.setShortcut("Ctrl+Shift+S")
        saveas_action.triggered.connect(self.saveas_file)
        file_menu.addAction(saveas_action)
        file_menu.addSeparator()
        exit_action = QAction("退出", self)
        exit_action.setShortcut("Ctrl+Q")
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        # 插入菜单
        insert_menu = menubar.addMenu("插入")
        for name in self.snippets.keys():
            action = QAction(name, self)
            action.triggered.connect(lambda checked, n=name: self.insert_snippet(n))
            insert_menu.addAction(action)
        # 工具菜单
        tools_menu = menubar.addMenu("工具")
        check_action = QAction("语法检查", self)
        check_action.setShortcut("F5")
        check_action.triggered.connect(self.check_syntax)
        tools_menu.addAction(check_action)
        format_action = QAction("格式化代码", self)
        format_action.setShortcut("Ctrl+Shift+F")
        format_action.triggered.connect(self.format_code)
        tools_menu.addAction(format_action)
        # 窗口菜单
        self.window_menu = menubar.addMenu("窗口")
        self.update_window_menu()
    
    def update_window_menu(self):
        if not self.window_menu:
            return
        self.window_menu.clear()
        for idx in range(len(self.opened_files)):
            filename = self.opened_files[idx]["filename"]
            title = os.path.basename(filename) if filename else f"未命名{idx+1}"
            # 菜单项文本：文档名 + 空格 + ×
            display_text = f"{title}    ×"
            action = QAction(display_text, self)
            action.setCheckable(True)
            action.setChecked(idx == self.current_file_index)
            # 传递索引和事件对象
            def handler(checked, i=idx):
                # 获取鼠标位置，判断是否点击在“×”区域
                pos = self.window_menu.cursor().pos()
                action_rect = self.window_menu.actionGeometry(action)
                # 估算“×”区域在右侧20像素
                if pos.x() > action_rect.right() - 20:
                    self.close_file(i)
                else:
                    self.switch_to_file(i)
            action.triggered.connect(handler)
            self.window_menu.addAction(action)
        if not self.opened_files:
            self.current_file_index = -1
            self.editor.setText("")
            self.update_title_status()

    def close_file(self, idx):
        # 关闭指定文档，若有修改则提示保存
        if idx < 0 or idx >= len(self.opened_files):
            return
        fileobj = self.opened_files[idx]
        if fileobj["modified"]:
            self.switch_to_file(idx)
            reply = QMessageBox.question(self, "保存文件", "文件有修改，是否保存？", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
            if reply == QMessageBox.Yes:
                if not self.save_file(idx):
                    return
            elif reply == QMessageBox.Cancel:
                return
        del self.opened_files[idx]
        # 关闭后切换到其它文档
        if self.opened_files:
            if idx == self.current_file_index:
                self.current_file_index = min(idx, len(self.opened_files)-1)
                self.switch_to_file(self.current_file_index)
            elif idx < self.current_file_index:
                self.current_file_index -= 1
        else:
            self.current_file_index = -1
            self.editor.setText("")
            self.update_title_status()
        self.update_window_menu()

    def new_file(self):
        # 新建文档，内容为空，未命名
        self.save_current_file_content()
        self.opened_files.append({"filename": None, "content": "", "modified": False})
        self.current_file_index = len(self.opened_files) - 1
        self.editor.setText("")
        self.update_title_status()
        self.update_window_menu()
    
    def open_file(self):
        fname, _ = QFileDialog.getOpenFileName(self, "打开脚本文件", "", "C# Files (*.cs);;Text Files (*.txt);;All Files (*)")
        if fname:
            self.open_files_from_drop([fname])
    
    def save_file(self, idx=None):
        if idx is None:
            idx = self.current_file_index
        if idx < 0 or idx >= len(self.opened_files):
            return False
        fileobj = self.opened_files[idx]
        filename = fileobj["filename"]
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(self.editor.text() if idx == self.current_file_index else fileobj["content"])
                self.opened_files[idx]["modified"] = False
                self.statusBar().showMessage(f"保存文件: {filename}")
                self.update_title_status()
                return True
            except Exception as e:
                QMessageBox.critical(self, "错误", f"无法保存文件: {str(e)}")
                return False
        else:
            return self.saveas_file()
    
    def saveas_file(self):
        idx = self.current_file_index
        fname, _ = QFileDialog.getSaveFileName(self, "另存为", "", "C# Files (*.cs);;Text Files (*.txt);;All Files (*)")
        if fname:
            try:
                with open(fname, 'w', encoding='utf-8') as f:
                    f.write(self.editor.text())
                self.opened_files[idx]["filename"] = fname
                self.opened_files[idx]["modified"] = False
                self.update_title_status()
                self.update_window_menu()
                self.statusBar().showMessage(f"另存为: {fname}")
                return True
            except Exception as e:
                QMessageBox.critical(self, "错误", f"无法保存文件: {str(e)}")
                return False
        return False
    
    def insert_snippet(self, name):
        if name in self.snippets:
            editor = self.editor
            cursor = editor.getCursorPosition()
            editor.insertAt(self.snippets[name], cursor[0], cursor[1])
            self.statusBar().showMessage(f"插入代码片段: {name}")
    
    def insert_snippet_from_list(self, item):
        name = item.text()
        self.insert_snippet(name)
    
    def save_snippets(self):
        data = [{"name": k, "content": v} for k, v in self.snippets.items()]
        with open("snippets.json", "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    
    def add_snippet(self):
        dialog = SnippetDialog(self)
        if dialog.exec_() == QDialog.Accepted:
            name, content = dialog.get_data()
            if name and content:
                self.snippets[name] = content
                self.refresh_snippet_list()
                self.statusBar().showMessage(f"添加代码片段: {name}")
                self.save_snippets()
    
    def edit_snippet(self):
        current_item = self.snippet_list.currentItem()
        if not current_item:
            QMessageBox.warning(self, "警告", "请先选择一个代码片段")
            return
        
        name = current_item.text()
        content = self.snippets.get(name, "")
        
        dialog = SnippetDialog(self, name, content)
        if dialog.exec_() == QDialog.Accepted:
            new_name, new_content = dialog.get_data()
            if new_name and new_content:
                if new_name != name:
                    del self.snippets[name]
                self.snippets[new_name] = new_content
                self.refresh_snippet_list()
                self.statusBar().showMessage(f"编辑代码片段: {new_name}")
                self.save_snippets()
    
    def delete_snippet(self):
        current_item = self.snippet_list.currentItem()
        if not current_item:
            QMessageBox.warning(self, "警告", "请先选择一个代码片段")
            return
        
        name = current_item.text()
        reply = QMessageBox.question(self, "确认删除", 
                                   f"确定要删除代码片段 '{name}' 吗？",
                                   QMessageBox.Yes | QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            del self.snippets[name]
            self.refresh_snippet_list()
            self.statusBar().showMessage(f"删除代码片段: {name}")
            self.save_snippets()
    
    def check_syntax(self):
        text = self.editor.text()
        errors, warnings = SyntaxChecker.check_syntax(text)
        
        if not errors and not warnings:
            QMessageBox.information(self, "语法检查", "语法检查通过！")
            self.statusBar().showMessage("语法检查通过")
        else:
            error_msg = "语法检查结果:\n\n"
            if errors:
                error_msg += "错误:\n" + "\n".join(f"• {error}" for error in errors) + "\n\n"
            if warnings:
                error_msg += "警告:\n" + "\n".join(f"• {warning}" for warning in warnings)
            
            QMessageBox.warning(self, "语法检查", error_msg)
            self.statusBar().showMessage(f"发现 {len(errors)} 个错误, {len(warnings)} 个警告")
    
    def format_code(self):
        text = self.editor.text()
        lines = text.split('\n')
        formatted_lines = []
        indent_level = 0
        
        for line in lines:
            stripped = line.strip()
            if not stripped:
                formatted_lines.append('')
                continue
            
            if stripped.startswith('}') or stripped.startswith('#endregion'):
                indent_level = max(0, indent_level - 1)
            
            formatted_line = '    ' * indent_level + stripped
            formatted_lines.append(formatted_line)
            
            if stripped.endswith('{') or stripped.startswith('#region'):
                indent_level += 1
        
        self.editor.setText('\n'.join(formatted_lines))
        self.statusBar().showMessage("代码格式化完成")
    
    def on_text_changed(self):
        if 0 <= self.current_file_index < len(self.opened_files):
            self.opened_files[self.current_file_index]["modified"] = True
        self.update_title_status()
    
    def move_snippet_up(self):
        row = self.snippet_list.currentRow()
        if row > 0:
            key_list = list(self.snippets.keys())
            key_list[row-1], key_list[row] = key_list[row], key_list[row-1]
            self.snippets = {k: self.snippets[k] for k in key_list}
            self.refresh_snippet_list()
            self.snippet_list.setCurrentRow(row-1)
            self.save_snippets()
    def move_snippet_down(self):
        row = self.snippet_list.currentRow()
        if row < self.snippet_list.count()-1 and row != -1:
            key_list = list(self.snippets.keys())
            key_list[row+1], key_list[row] = key_list[row], key_list[row+1]
            self.snippets = {k: self.snippets[k] for k in key_list}
            self.refresh_snippet_list()
            self.snippet_list.setCurrentRow(row+1)
            self.save_snippets()
    
    def closeEvent(self, event):
        # 检查所有已打开文档是否有未保存
        for idx, fileobj in enumerate(self.opened_files):
            if fileobj["modified"]:
                self.switch_to_file(idx)
                reply = QMessageBox.question(self, "保存文件", "有未保存的文件，是否保存？", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if reply == QMessageBox.Yes:
                    if not self.save_file(idx):
                        event.ignore()
                        return
                elif reply == QMessageBox.Cancel:
                    event.ignore()
                    return
        event.accept()

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            urls = event.mimeData().urls()
            if urls:
                self.open_files_from_drop([u.toLocalFile() for u in urls])
        else:
            event.ignore()

    def open_files_from_drop(self, file_list):
        self.save_current_file_content()
        for file_path in file_list:
            if os.path.isfile(file_path):
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                    # 检查是否已打开
                    for i, fobj in enumerate(self.opened_files):
                        if fobj["filename"] == file_path:
                            self.switch_to_file(i)
                            break
                    else:
                        self.opened_files.append({"filename": file_path, "content": content, "modified": False})
                        self.switch_to_file(len(self.opened_files) - 1)
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"无法打开文件: {str(e)}")
        # 打开文档后自动关闭空白未命名文档
        self.close_empty_unnamed_files()
        self.update_window_menu()

    def close_empty_unnamed_files(self):
        # 关闭所有内容为空的未命名文档（保留当前文档）
        to_delete = []
        for i, fobj in enumerate(self.opened_files):
            if not fobj["filename"] and not fobj["content"] and i != self.current_file_index:
                to_delete.append(i)
        for idx in reversed(to_delete):
            del self.opened_files[idx]
            if idx < self.current_file_index:
                self.current_file_index -= 1
        if not self.opened_files:
            self.current_file_index = -1
            self.editor.setText("")
            self.update_title_status()

    def refresh_snippet_list(self):
        self.snippet_list.clear()
        for name in self.snippets.keys():
            self.snippet_list.addItem(name)

    def switch_to_file(self, idx):
        # 切换文档时不做任何保存、弹窗、状态修改，只切换索引并加载内容
        if idx == self.current_file_index:
            return
        self.current_file_index = idx
        fileobj = self.opened_files[idx]
        self.editor.setText(fileobj["content"])
        self.update_title_status()
        self.update_window_menu()

    def save_current_file_content(self):
        if 0 <= self.current_file_index < len(self.opened_files):
            self.opened_files[self.current_file_index]["content"] = self.editor.text()

def main():
    app = QApplication(sys.argv)
    app.setApplicationName("C#脚本编辑器")
    app.setApplicationVersion("1.0")
    
    editor = ScriptEditor()
    editor.show()
    
    sys.exit(app.exec_())

if __name__ == "__main__":
    main() 